#!/usr/bin/python
import os
import sys
import errno
import uuid
import subprocess
import time
from utils import _print1, _print2, _get_value, Exp, _exec_pipe

tmp_file = "/dev/shm/tmp.xxxx"

class List_test:
    def __init__(self, count, path, cmd, log_cmd):
        if (path[0] != '/' or path.find("//") != -1):
            return None
            #raise Exception("errno.EINVAL")

        if (path[len(path) - 1] == '/' and path != "/"):
            return None

        if (path == "/"):
            self.type = "namespace"
        elif (len(path.split('/')) == 2) :
            self.type = "bucket"
        elif (len(path.split('/')) == 3) :
            self.type = "object"
        else:
            return None
            #raise Exception("errno.EINVAL")


        #print("create list %s type %s\n" %(path, self.type))

        self.path = path
        self.count = count
        self.list = []
        self.cmd = cmd
        self.attr = cmd + '.attr'
        self.log_cmd = log_cmd

        for i in range(self.count):
            self.list.append(str(uuid.uuid1()))

    def insert(self, i):
        if (self.type  == "namespace"):
            cmd = self.cmd + " --create /%s %s" %(self.list[i], self.log_cmd)
            attr = self.attr + " --set %s --value %s  /%s %s" %(self.list[i], self.list[i], self.list[i], self.log_cmd)
        elif (self.type == "bucket"):
            cmd = self.cmd + " --create %s/%s %s" %(self.path, self.list[i], self.log_cmd)
            attr = self.attr + " --set %s --value %s %s/%s %s" %(self.list[i], self.list[i], self.path, self.list[i], self.log_cmd)
        else:
            return self.insert_object(self.list[i], i)
        print(cmd + "(%u/%u)" %(i + 1, self.count))
        print(attr + "(%u/%u)" %(i + 1, self.count))

        retry = 0
        while (1):
            ret = subprocess.call(cmd, shell=True)
            if (ret != 0):
                if (retry > 40):
                    raise Exp(ret, "insert fail")
                print ("error:" + cmd + ",retry:%d" % (retry))
                if (ret == errno.EEXIST and retry > 0):
                    cmd1 = ""
                    if (self.type  == "namespace"):
                        cmd1 = self.cmd + " --remove /%s %s" %(self.list[i], self.log_cmd)
                    elif (self.type == "bucket"):
                        cmd1 = self.cmd + " --remove %s/%s %s" %(self.path, self.list[i], self.log_cmd)
                    print(cmd1)
                    subprocess.call(cmd1, shell=True)
                    time.sleep(1)
                    retry = retry + 1
                    continue
                elif (ret == errno.EAGAIN or ret == errno.ENONET
                      or ret == errno.ENOSYS):
                    time.sleep(1)
                    retry = retry + 1
                    print ("retry : %s" % (cmd))
                else:
                    raise Exp(ret, "insert fail retry %d %s" % (retry, cmd))
            else:
                break

        retry = 0
        while (1):
            ret = subprocess.call(attr, shell=True)
            ret = subprocess.call(attr, shell=True)
            ret = subprocess.call(attr, shell=True)
            if (ret != 0):
                if (retry > 40):
                    raise Exp(ret, "set fail")
                print ("error:" + attr + ",retry:%d" % (retry))
                if (ret == errno.EAGAIN or ret == errno.ENONET
                      or ret == errno.ENOSYS):
                    time.sleep(1)
                    retry = retry + 1
                    print ("retry : %s" % (attr))
                else:
                    raise Exp(ret, "set fail retry %d %s" % (retry, attr))
            else:
                break

    def insert_object(self, string, i):
        cmd = "echo %s > %s && " % (string, tmp_file)
        cmd = cmd + self.cmd + " --clone :%s %s/%s %s &&" %(tmp_file, self.path, string, self.log_cmd)
        cmd = cmd +  "rm " + tmp_file
        print(cmd + "(%u/%u)" %(i + 1, self.count))

        retry = 0
        while (1):
            ret = subprocess.call(cmd, shell=True)
            if (ret != 0):
                if (retry > 40):
                    raise Exp(ret, "insert fail")
                if (ret == errno.EEXIST and retry > 0):
                    cmd1 = self.cmd + " --remove %s/%s" %(self.path, string)
                    retry = retry + 1
                    time.sleep(1)
                    print(cmd1)
                    subprocess.call(cmd1, shell=True)
                    continue
                elif (ret == errno.EAGAIN or ret == errno.ENONET
                      or ret == errno.ENOSYS):
                    time.sleep(1)
                    retry = retry + 1
                    print ("retry : %s" % (cmd))
                else:
                    raise Exp(ret, "insert object fail retry %d" % (retry))
            else:
                break

    def check(self, i):
        if (len(self.log_cmd) == 0):
            log_cmd = " > /dev/null"
        else:
            log_cmd = self.log_cmd
        if (self.type  == "namespace"):
            cmd = self.cmd + " --stat /%s %s" %(self.list[i], log_cmd)
            attr = self.attr + " --get %s /%s" %(self.list[i], self.list[i])
            attr = [self.attr,"--get", self.list[i], '/' + self.list[i]]
        elif (self.type == "bucket"):
            cmd = self.cmd + " --stat %s/%s %s" %(self.path, self.list[i], log_cmd)
            attr = [self.attr,"--get", self.list[i], self.path + '/' + self.list[i]]
        else:
            return self.check_object(self.list[i], i)
        print(cmd + "(%u/%u)" %(i + 1, self.count))
        print(str(attr) + "(%u/%u)" %(i + 1, self.count))

        retry = 0
        while (1):
            ret = subprocess.call(cmd, shell=True)
            if (ret != 0):
                if (retry > 40):
                    raise Exp(ret, "check fail")
                if (ret == errno.EAGAIN or ret == errno.ENONET
                    or ret == errno.ENOSYS):
                    time.sleep(1)
                    retry = retry + 1
                    print ("retry : %s" % (cmd))
                    continue
                else:
                    raise Exp(ret, "check fail")
            else:
                break

        retry = 0
        while (1):
            try:
                res = _exec_pipe(attr)
            except Exp, e:
                if (retry > 40):
                    raise Exp(ret, "check fail")
                if (e.errno == errno.EAGAIN or e.errno == errno.ENONET
                    or e.errno == errno.ENOSYS):
                    time.sleep(1)
                    retry = retry + 1
                    print ("retry : %s" % (str(attr)))
                    continue
                else:
                    raise Exp(e.errno, "check fail")
            else:
                break

        #print(self.list[i])
        #print(res)
        if (res[:-1] != self.list[i]):
            raise Exp(errno.EIO, "attr check fail")

    def check_object(self, string, i):
        cmd = "rm -rf %s &&" % (tmp_file)
        cmd = cmd + self.cmd + " --clone %s/%s :%s %s" %(self.path, string, tmp_file, self.log_cmd)
        print(cmd + "(%u/%u)" %(i + 1, self.count))

        retry = 0
        while (1):
            ret = subprocess.call(cmd, shell=True)
            if (ret != 0):
                if (retry > 40):
                    raise Exp(ret, "check fail")
                if (ret == errno.EAGAIN or ret == errno.ENONET
                    or ret == errno.ENOSYS):
                    time.sleep(1)
                    retry = retry + 1
                    print ("retry : %s" % (cmd))
                else:
                    raise Exp(ret, "check object fail")
            else:
                break

        buf = _get_value(tmp_file)
        if (buf != string + "\n"):
            raise Exp(errno.EIO, "check object fail")
